package org.zch.common.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;
import org.zch.common.constant.RedisConstant;

import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 订单编码码生成器，生成32位数字编码，
 *
 * @author 刘新
 * @生成规则 1位单号类型+17位时间戳+14位(用户id加密&随机数)
 * Date:2023年12月29日上午10:05:19
 */
@Component
public class CodeNoUtil {

    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 生成时间戳
     */
    private String getDateTime() {
        DateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");
        return sdf.format(new Date());
    }

    /**
     * 生成时间戳
     */
    private String getDate() {
        DateFormat sdf = new SimpleDateFormat("yyMMdd");
        return sdf.format(new Date());
    }

    /**
     * 生成固定长度随机码
     *
     * @param n 长度
     */
    public long getRandom(long n) {
        long min = 1, max = 9;
        for (int i = 1; i < n; i++) {
            min *= 10;
            max *= 10;
        }
        long rangeLong = (((long) (new Random().nextDouble() * (max - min)))) + min;
        return rangeLong;
    }

    /**
     * 生成不重复随机数
     * n 随机数长度
     * keyNO 随机数的前缀
     */
    public String getCode(long n, String keyNo) {
        long random = getRandom(n);
        String code = String.valueOf(random);
        // 从redis获取code，判断是否重复，如果重复则重新生成随机数
        Boolean hasKey = redisTemplate.hasKey(keyNo + code);
        if (hasKey){
            // 如果存在重复数据，则重新生成
            code = getCode(n, keyNo);
        }
        // 计算今天24点的时间戳
        long expirationTime = LocalDateTime.now().plusDays(1).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        // 存入redis，并设置今天过期
        long timeout = expirationTime - System.currentTimeMillis();
        redisTemplate.opsForValue().set(keyNo + code, code, timeout, TimeUnit.MILLISECONDS);
        return code;
    }

    /**
     * 生成用户编码
     */
    public String getUserCode() {
        Long code = incr(RedisConstant.USER_CODE_SEQ);
        DecimalFormat df = new DecimalFormat("000000");
        // HL表示话痨标识  A表示该code为用户code和后续其他类型code作为区分
        //return "HL" + "A" + "_" + df.format(code);
        return df.format(code);
    }

    public Long incr(String key) {
        Long increment = 0L;
        try {
            RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
            increment = entityIdCounter.incrementAndGet();
        } catch (Exception e) {
        }
        return increment;
    }


    /**
     * 生成订单号
     */
    public String getOrderNo() {
        String orderNo = "OR";
        String date = getDate();
        String code = getCode(4, orderNo);
        return orderNo + date + code;
    }
}
